package com.sale.salesystem.service.impl;

import com.sale.salesystem.dto.*;
import com.sale.salesystem.entity.*;
import com.sale.salesystem.mapper.*;
import com.sale.salesystem.service.DashboardService;
import com.sale.salesystem.vo.*;
import com.sale.salesystem.exception.BusinessException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import com.fasterxml.jackson.databind.ObjectMapper;

@Service
@Slf4j
@RequiredArgsConstructor
public class DashboardServiceImpl implements DashboardService {

    private final SalesDailyDataMapper salesDailyDataMapper;
    private final DashboardInfoMapper dashboardInfoMapper;
    private final DashboardChartMapper dashboardChartMapper;
    private final DashboardPermissionMapper permissionMapper;
    private final ReportDataMapper reportDataMapper;
    private final ChartTypeMapper chartTypeMapper;
    private final DataSourceMapper dataSourceMapper;
    private final UserMapper userMapper;

    @Override
    public DashboardVO getAnalysisData(DashboardQueryDTO queryDTO) {
        DashboardVO dashboardVO = new DashboardVO();
        dashboardVO.setKpiData(getKpiData(queryDTO));
        dashboardVO.setChartData(getChartData(queryDTO));
        return dashboardVO;
    }

    @Override
    public List<String> getAllCategories() {
        List<String> categories = salesDailyDataMapper.selectAllCategories();
        return categories;
    }

    @Override
    public List<String> getAllCities() {
        List<String> cities = salesDailyDataMapper.selectAllCities();
        return cities;
    }

    @Override
    public List<Long> getAllShopCodes() {
        List<Long> shopCodes = salesDailyDataMapper.selectAllShopCodes();
        return shopCodes;
    }

    @Override
    public List<String> getAllGenders() {
        return Arrays.asList("男", "女");
    }

    @Override
    public List<String> getAllAgeRanges() {
        return Arrays.asList("<20", "20-24", "25-29", "30-34", "35-39", "40-44", "45-49", "50-54", "55-59", ">=60");
    }

    @Override
    public DashboardVO.KpiDataVO getKpiData(DashboardQueryDTO queryDTO) {
        DashboardVO.KpiDataVO kpiData = new DashboardVO.KpiDataVO();

        // 获取查询时间范围
        LocalDate endDate = queryDTO.getEndDate();
        LocalDate startDate = queryDTO.getStartDate();

        // 获取当前数据
        List<SalesDailyData> currentData = salesDailyDataMapper.selectByConditions(
                startDate,
                endDate,
                queryDTO.getCategory(),
                queryDTO.getCity(),
                queryDTO.getShopId(),
                queryDTO.getGender(),
                queryDTO.getAgeRange()
        );

        // 如果没有指定日期范围，则不计算同比和环比
        if (startDate == null || endDate == null) {
            // 汇总当前数据
            BigDecimal totalSales = currentData.stream()
                    .map(SalesDailyData::getTotalSales)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            BigDecimal totalProfit = currentData.stream()
                    .map(SalesDailyData::getTotalProfit)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            int orderCount = currentData.stream()
                    .mapToInt(SalesDailyData::getOrderCount)
                    .sum();

            int salesVolume = currentData.stream()
                    .mapToInt(SalesDailyData::getSalesVolume)
                    .sum();

            int customerCount = currentData.stream()
                    .mapToInt(SalesDailyData::getCustomerCount)
                    .sum();

            // 设置KPI数据
            kpiData.setTotalSales(totalSales);
            kpiData.setTotalProfit(totalProfit);
            kpiData.setOrderCount(orderCount);
            kpiData.setSalesVolume(salesVolume);
            kpiData.setCustomerCount(customerCount);

            // 设置同比环比为0
            kpiData.setSalesWeekOnWeek(0.0);
            kpiData.setSalesDayOnDay(0.0);
            kpiData.setProfitWeekOnWeek(0.0);
            kpiData.setProfitDayOnDay(0.0);
            kpiData.setOrderWeekOnWeek(0.0);
            kpiData.setOrderDayOnDay(0.0);
            kpiData.setVolumeWeekOnWeek(0.0);
            kpiData.setVolumeDayOnDay(0.0);
            kpiData.setCustomerWeekOnWeek(0.0);
            kpiData.setCustomerDayOnDay(0.0);

            return kpiData;
        }

        // 计算同期数据（上周同期）
        LocalDate lastWeekStart = startDate.minusWeeks(1);
        LocalDate lastWeekEnd = endDate.minusWeeks(1);
        List<SalesDailyData> lastWeekData = salesDailyDataMapper.selectByDateRange(lastWeekStart, lastWeekEnd);

        // 计算环比数据（前一天）
        LocalDate yesterday = endDate.minusDays(1);
        List<SalesDailyData> yesterdayData = salesDailyDataMapper.selectByDate(yesterday);

        // 汇总当前数据
        BigDecimal totalSales = currentData.stream()
                .map(SalesDailyData::getTotalSales)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        BigDecimal totalProfit = currentData.stream()
                .map(SalesDailyData::getTotalProfit)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        int orderCount = currentData.stream()
                .mapToInt(SalesDailyData::getOrderCount)
                .sum();

        int salesVolume = currentData.stream()
                .mapToInt(SalesDailyData::getSalesVolume)
                .sum();

        int customerCount = currentData.stream()
                .mapToInt(SalesDailyData::getCustomerCount)
                .sum();

        // 设置KPI数据
        kpiData.setTotalSales(totalSales);
        kpiData.setTotalProfit(totalProfit);
        kpiData.setOrderCount(orderCount);
        kpiData.setSalesVolume(salesVolume);
        kpiData.setCustomerCount(customerCount);

        // 计算周同比和日环比
        calculateRatios(kpiData, currentData, lastWeekData, yesterdayData);

        return kpiData;
    }

    @Override
    public DashboardVO.ChartDataVO getChartData(DashboardQueryDTO queryDTO) {
        DashboardVO.ChartDataVO chartData = new DashboardVO.ChartDataVO();

        // 获取最近6个月的数据
        LocalDate startDate = LocalDate.of(2023, 1, 1);  // 2023年1月1日
        LocalDate endDate = LocalDate.of(2023, 12, 31); // 2023年12月31日


        List<SalesDailyData> monthlyData = salesDailyDataMapper.selectByConditions(
                startDate, endDate,
                queryDTO.getCategory(),
                queryDTO.getCity(),
                queryDTO.getShopId(),
                queryDTO.getGender(),
                queryDTO.getAgeRange()
        );

        // 按月份分组数据
        Map<String, List<SalesDailyData>> groupedData = monthlyData.stream()
                .collect(Collectors.groupingBy(data ->
                        data.getDate().getMonth().toString()));

        // 准备图表数据
        List<String> months = new ArrayList<>();
        List<BigDecimal> sales = new ArrayList<>();
        List<BigDecimal> profits = new ArrayList<>();
        List<Integer> orders = new ArrayList<>();
        List<Integer> volumes = new ArrayList<>();
        List<Integer> customers = new ArrayList<>();

        // 按月份汇总数据
        groupedData.forEach((month, data) -> {
            months.add(month);
            sales.add(data.stream()
                    .map(SalesDailyData::getTotalSales)
                    .reduce(BigDecimal.ZERO, BigDecimal::add));
            profits.add(data.stream()
                    .map(SalesDailyData::getTotalProfit)
                    .reduce(BigDecimal.ZERO, BigDecimal::add));
            orders.add(data.stream()
                    .mapToInt(SalesDailyData::getOrderCount)
                    .sum());
            volumes.add(data.stream()
                    .mapToInt(SalesDailyData::getSalesVolume)
                    .sum());
            customers.add(data.stream()
                    .mapToInt(SalesDailyData::getCustomerCount)
                    .sum());
        });

        // 设置图表数据
        chartData.setMonths(months);
        chartData.setSales(sales);
        chartData.setProfits(profits);
        chartData.setOrders(orders);
        chartData.setVolumes(volumes);
        chartData.setCustomers(customers);

        return chartData;
    }

    // 计算同比和环比
    private void calculateRatios(
            DashboardVO.KpiDataVO kpiData,
            List<SalesDailyData> currentData,
            List<SalesDailyData> lastWeekData,
            List<SalesDailyData> yesterdayData
    ) {
        // 计算上周同期数据
        BigDecimal lastWeekSales = lastWeekData.stream()
                .map(SalesDailyData::getTotalSales)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        BigDecimal lastWeekProfit = lastWeekData.stream()
                .map(SalesDailyData::getTotalProfit)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        int lastWeekOrders = lastWeekData.stream()
                .mapToInt(SalesDailyData::getOrderCount)
                .sum();

        int lastWeekVolume = lastWeekData.stream()
                .mapToInt(SalesDailyData::getSalesVolume)
                .sum();

        int lastWeekCustomers = lastWeekData.stream()
                .mapToInt(SalesDailyData::getCustomerCount)
                .sum();

        // 计算昨日数据
        BigDecimal yesterdaySales = yesterdayData.stream()
                .map(SalesDailyData::getTotalSales)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        BigDecimal yesterdayProfit = yesterdayData.stream()
                .map(SalesDailyData::getTotalProfit)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        int yesterdayOrders = yesterdayData.stream()
                .mapToInt(SalesDailyData::getOrderCount)
                .sum();

        int yesterdayVolume = yesterdayData.stream()
                .mapToInt(SalesDailyData::getSalesVolume)
                .sum();

        int yesterdayCustomers = yesterdayData.stream()
                .mapToInt(SalesDailyData::getCustomerCount)
                .sum();

        // 设置周同比
        kpiData.setSalesWeekOnWeek(calculateGrowthRate(kpiData.getTotalSales(), lastWeekSales));
        kpiData.setProfitWeekOnWeek(calculateGrowthRate(kpiData.getTotalProfit(), lastWeekProfit));
        kpiData.setOrderWeekOnWeek(calculateGrowthRate(kpiData.getOrderCount(), lastWeekOrders));
        kpiData.setVolumeWeekOnWeek(calculateGrowthRate(kpiData.getSalesVolume(), lastWeekVolume));
        kpiData.setCustomerWeekOnWeek(calculateGrowthRate(kpiData.getCustomerCount(), lastWeekCustomers));

        // 设置日环比
        kpiData.setSalesDayOnDay(calculateGrowthRate(kpiData.getTotalSales(), yesterdaySales));
        kpiData.setProfitDayOnDay(calculateGrowthRate(kpiData.getTotalProfit(), yesterdayProfit));
        kpiData.setOrderDayOnDay(calculateGrowthRate(kpiData.getOrderCount(), yesterdayOrders));
        kpiData.setVolumeDayOnDay(calculateGrowthRate(kpiData.getSalesVolume(), yesterdayVolume));
        kpiData.setCustomerDayOnDay(calculateGrowthRate(kpiData.getCustomerCount(), yesterdayCustomers));
    }

    // 计算增长率
    private Double calculateGrowthRate(BigDecimal current, BigDecimal previous) {
        if (previous.equals(BigDecimal.ZERO)) {
            return 0.0;
        }
        return current.subtract(previous)
                .multiply(new BigDecimal("100"))
                .divide(previous, 2, RoundingMode.HALF_UP)
                .doubleValue();
    }

    private Double calculateGrowthRate(Integer current, Integer previous) {
        if (previous == 0) {
            return 0.0;
        }
        return ((double) (current - previous) / previous) * 100;
    }

    @Override
    public ProductAnalysisVO getProductAnalysis(DashboardQueryDTO queryDTO) {
        ProductAnalysisVO result = new ProductAnalysisVO();

        // 1. 获取查询时间范围
        LocalDate endDate = queryDTO.getEndDate();
        LocalDate startDate = queryDTO.getStartDate();

        // 如果没有指定时间范围，默认查询全年数据
        if (startDate == null || endDate == null) {
            endDate = LocalDate.of(2023, 12, 31);
            startDate = endDate.withDayOfYear(1); // 当年第一天
        }

        // 2. 查询数据
        List<SalesDailyData> salesData = salesDailyDataMapper.selectByConditions(
                startDate, endDate,
                queryDTO.getCategory(),
                null, // city
                null, // shopId
                null, // gender
                null  // ageRange
        );

        if (salesData.isEmpty()) {
            return result;
        }

        // 3. 处理销量趋势数据（不受产品类别影响）
        ProductAnalysisVO.ProductTrendVO volumeTrendVO = new ProductAnalysisVO.ProductTrendVO();
        Map<String, List<SalesDailyData>> allVolumeByMonth = salesData.stream()
                .collect(Collectors.groupingBy(data ->
                        data.getDate().getMonth().toString()));

        // 准备月份列表（按时间顺序）
        List<String> months = allVolumeByMonth.keySet().stream()
                .sorted()
                .collect(Collectors.toList());

        List<Integer> totalVolumes = new ArrayList<>();

        // 计算每月总销量
        for (String month : months) {
            int monthVolume = allVolumeByMonth.get(month).stream()
                    .mapToInt(SalesDailyData::getSalesVolume)
                    .sum();
            totalVolumes.add(monthVolume);
        }

        volumeTrendVO.setMonths(months);
        volumeTrendVO.setVolumes(totalVolumes);
        result.setProductTrend(volumeTrendVO);

        // 4. 如果指定了产品类别，则处理类别相关的趋势数据
        if (queryDTO.getCategory() != null) {
            ProductAnalysisVO.ProductTrendVO categoryTrendVO = new ProductAnalysisVO.ProductTrendVO();

            // 按月份分组，但只处理指定类别的数据
            Map<String, List<SalesDailyData>> groupedByMonth = salesData.stream()
                    .filter(data -> queryDTO.getCategory().equals(data.getCategory()))
                    .collect(Collectors.groupingBy(data ->
                            data.getDate().getMonth().toString()));

            List<String> categoryMonths = groupedByMonth.keySet().stream()
                    .sorted()
                    .collect(Collectors.toList());

            List<BigDecimal> prices = new ArrayList<>();
            List<BigDecimal> profits = new ArrayList<>();
            List<Integer> volumes = new ArrayList<>();
            List<BigDecimal> sales = new ArrayList<>();

            // 计算每月数据
            for (String month : categoryMonths) {
                List<SalesDailyData> monthData = groupedByMonth.get(month);

                // 销售量
                int monthVolume = monthData.stream()
                        .mapToInt(SalesDailyData::getSalesVolume)
                        .sum();
                volumes.add(monthVolume);

                // 销售额
                BigDecimal monthSales = monthData.stream()
                        .map(SalesDailyData::getTotalSales)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                sales.add(monthSales);

                // 利润
                BigDecimal monthProfit = monthData.stream()
                        .map(SalesDailyData::getTotalProfit)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);

                // 平均利润（每件商品的平均利润）
                if (monthVolume > 0) {
                    profits.add(monthProfit.divide(new BigDecimal(monthVolume), 2, RoundingMode.HALF_UP));
                } else {
                    profits.add(BigDecimal.ZERO);
                }

                // 平均单价（每件商品的平均售价）
                if (monthVolume > 0) {
                    prices.add(monthSales.divide(new BigDecimal(monthVolume), 2, RoundingMode.HALF_UP));
                } else {
                    prices.add(BigDecimal.ZERO);
                }
            }

            categoryTrendVO.setMonths(categoryMonths);
            categoryTrendVO.setPrices(prices);
            categoryTrendVO.setProfits(profits);
            categoryTrendVO.setVolumes(volumes);
            categoryTrendVO.setSales(sales);

            // 更新类别趋势数据
            result.setCategoryTrend(categoryTrendVO);
        }

        // 5. 处理产品排名和占比数据
        // 3. 按产品类别分组汇总数据
        Map<String, List<SalesDailyData>> groupedByCategory = salesData.stream()
                .collect(Collectors.groupingBy(SalesDailyData::getCategory));

        // 4. 计算每个类别的销售总量和销售总额
        List<ProductAnalysisVO.ProductRankVO> categoryStats = groupedByCategory.entrySet().stream()
                .map(entry -> {
                    ProductAnalysisVO.ProductRankVO rankVO = new ProductAnalysisVO.ProductRankVO();
                    rankVO.setCategory(entry.getKey());
                    rankVO.setSalesVolume(entry.getValue().stream()
                            .mapToInt(SalesDailyData::getSalesVolume)
                            .sum());
                    rankVO.setSalesAmount(entry.getValue().stream()
                            .map(SalesDailyData::getTotalSales)
                            .reduce(BigDecimal.ZERO, BigDecimal::add));
                    return rankVO;
                })
                .sorted((a, b) -> b.getSalesAmount().compareTo(a.getSalesAmount()))
                .collect(Collectors.toList());

        // 5. 设置TOP5产品数据
        result.setTopProducts(categoryStats.stream()
                .limit(5)
                .collect(Collectors.toList()));

        // 6. 计算销售占比
        BigDecimal totalSales = categoryStats.stream()
                .map(ProductAnalysisVO.ProductRankVO::getSalesAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        List<ProductAnalysisVO.ProductShareVO> shares = categoryStats.stream()
                .map(stat -> {
                    ProductAnalysisVO.ProductShareVO shareVO = new ProductAnalysisVO.ProductShareVO();
                    shareVO.setCategory(stat.getCategory());
                    shareVO.setSalesAmount(stat.getSalesAmount());
                    if (totalSales.compareTo(BigDecimal.ZERO) > 0) {
                        shareVO.setPercentage(stat.getSalesAmount()
                                .multiply(new BigDecimal("100"))
                                .divide(totalSales, 2, RoundingMode.HALF_UP)
                                .doubleValue());
                    } else {
                        shareVO.setPercentage(0.0);
                    }
                    return shareVO;
                })
                .collect(Collectors.toList());

        result.setProductShares(shares);

        return result;
    }

    @Override
    public CustomerAnalysisVO getCustomerAnalysis(DashboardQueryDTO queryDTO) {
        CustomerAnalysisVO result = new CustomerAnalysisVO();

        // 1. 获取查询时间范围
        LocalDate endDate = queryDTO.getEndDate();
        LocalDate startDate = queryDTO.getStartDate();

        // 2. 查询数据
        List<SalesDailyData> salesData = salesDailyDataMapper.selectByConditions(
                startDate, endDate,
                queryDTO.getCategory(),
                null, // city
                null, // shopId
                null, // gender
                null  // ageRange
        );

        if (salesData.isEmpty()) {
            return result;
        }

        // 3. 计算KPI数据
        CustomerAnalysisVO.CustomerKpiVO kpiData = new CustomerAnalysisVO.CustomerKpiVO();

        // 3.1 计算当前数据
        int totalCustomers = salesData.stream()
                .mapToInt(SalesDailyData::getCustomerCount)
                .sum();

        // 3.2 计算新客户数（假设是当天新增的客户数）
        int newCustomers = salesData.stream()
                .filter(data -> data.getDate().equals(endDate))
                .mapToInt(SalesDailyData::getCustomerCount)
                .sum();

        // 3.3 计算同比环比
        if (startDate != null && endDate != null) {
            // 上周同期数据
            LocalDate lastWeekStart = startDate.minusWeeks(1);
            LocalDate lastWeekEnd = endDate.minusWeeks(1);
            List<SalesDailyData> lastWeekData = salesDailyDataMapper.selectByDateRange(lastWeekStart, lastWeekEnd);

            // 昨日数据
            LocalDate yesterday = endDate.minusDays(1);
            List<SalesDailyData> yesterdayData = salesDailyDataMapper.selectByDate(yesterday);

            // 计算上周客户数
            int lastWeekCustomers = lastWeekData.stream()
                    .mapToInt(SalesDailyData::getCustomerCount)
                    .sum();

            // 计算昨日客户数
            int yesterdayCustomers = yesterdayData.stream()
                    .mapToInt(SalesDailyData::getCustomerCount)
                    .sum();

            // 计算上周新客户数
            int lastWeekNewCustomers = lastWeekData.stream()
                    .filter(data -> data.getDate().equals(lastWeekEnd))
                    .mapToInt(SalesDailyData::getCustomerCount)
                    .sum();

            // 计算昨日新客户数
            int yesterdayNewCustomers = yesterdayData.stream()
                    .mapToInt(SalesDailyData::getCustomerCount)
                    .sum();

            // 设置同比环比
            kpiData.setWeekOnWeek(calculateGrowthRate(totalCustomers, lastWeekCustomers));
            kpiData.setDayOnDay(calculateGrowthRate(totalCustomers, yesterdayCustomers));
            kpiData.setNewWeekOnWeek(calculateGrowthRate(newCustomers, lastWeekNewCustomers));
            kpiData.setNewDayOnDay(calculateGrowthRate(newCustomers, yesterdayNewCustomers));
        }

        kpiData.setTotalCustomers(totalCustomers);
        kpiData.setNewCustomers(newCustomers);
        result.setKpiData(kpiData);

        // 4. 计算分布数据
        CustomerAnalysisVO.CustomerDistributionVO distribution = new CustomerAnalysisVO.CustomerDistributionVO();

        // 4.1 性别分布
        Map<String, List<SalesDailyData>> genderGroups = salesData.stream()
                .collect(Collectors.groupingBy(SalesDailyData::getGender));

        List<CustomerAnalysisVO.DistributionItemVO> genderDistribution = calculateDistribution(genderGroups);
        distribution.setGender(genderDistribution);

        // 4.2 年龄分布
        Map<String, List<SalesDailyData>> ageGroups = salesData.stream()
                .collect(Collectors.groupingBy(SalesDailyData::getAgeRange));

        List<CustomerAnalysisVO.DistributionItemVO> ageDistribution = calculateDistribution(ageGroups);
        distribution.setAge(ageDistribution);

        // 4.3 城市分布
        Map<String, List<SalesDailyData>> cityGroups = salesData.stream()
                .collect(Collectors.groupingBy(SalesDailyData::getCity));

        List<CustomerAnalysisVO.DistributionItemVO> cityDistribution = calculateDistribution(cityGroups);
        distribution.setCity(cityDistribution);

        // 4.4 消费时间分布（按星期）
        Map<String, List<SalesDailyData>> weekdayGroups = salesData.stream()
                .collect(Collectors.groupingBy(data -> data.getDate().getDayOfWeek().toString()));

        List<CustomerAnalysisVO.WeekdayDataVO> weekdayData = weekdayGroups.entrySet().stream()
                .map(entry -> {
                    CustomerAnalysisVO.WeekdayDataVO weekdayVO = new CustomerAnalysisVO.WeekdayDataVO();
                    weekdayVO.setWeekday(entry.getKey());
                    weekdayVO.setCount(entry.getValue().stream()
                            .mapToInt(SalesDailyData::getCustomerCount)
                            .sum());
                    return weekdayVO;
                })
                .sorted(Comparator.comparing(CustomerAnalysisVO.WeekdayDataVO::getWeekday))
                .collect(Collectors.toList());

        distribution.setWeekday(weekdayData);

        // 4.5 消费能力分布
        List<CustomerAnalysisVO.ConsumptionDataVO> consumptionData = new ArrayList<>();
        Map<String, Integer> consumptionRanges = new HashMap<>();

        salesData.forEach(data -> {
            BigDecimal avgConsumption = data.getTotalSales()
                    .divide(new BigDecimal(data.getCustomerCount()), 2, RoundingMode.HALF_UP);
            String range = getConsumptionRange(avgConsumption);
            consumptionRanges.merge(range, data.getCustomerCount(), Integer::sum);
        });

        consumptionRanges.forEach((range, count) -> {
            CustomerAnalysisVO.ConsumptionDataVO consumptionVO = new CustomerAnalysisVO.ConsumptionDataVO();
            consumptionVO.setRange(range);
            consumptionVO.setCount(count);
            consumptionData.add(consumptionVO);
        });

        distribution.setConsumption(consumptionData);
        result.setDistribution(distribution);

        // 5. 计算趋势数据
        CustomerAnalysisVO.CustomerTrendVO trend = new CustomerAnalysisVO.CustomerTrendVO();

        // 按月份分组
        Map<String, List<SalesDailyData>> monthlyData = salesData.stream()
                .collect(Collectors.groupingBy(data ->
                        data.getDate().getMonth().toString()));

        // 准备月份列表（按时间顺序）
        List<String> months = monthlyData.keySet().stream()
                .sorted()
                .collect(Collectors.toList());

        List<BigDecimal> avgConsumption = new ArrayList<>();
        List<BigDecimal> avgProfit = new ArrayList<>();

        // 计算每月数据
        for (String month : months) {
            List<SalesDailyData> monthData = monthlyData.get(month);

            int monthCustomers = monthData.stream()
                    .mapToInt(SalesDailyData::getCustomerCount)
                    .sum();

            if (monthCustomers > 0) {
                // 计算月度人均消费
                BigDecimal monthSales = monthData.stream()
                        .map(SalesDailyData::getTotalSales)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                avgConsumption.add(monthSales.divide(new BigDecimal(monthCustomers), 2, RoundingMode.HALF_UP));

                // 计算月度人均利润
                BigDecimal monthProfit = monthData.stream()
                        .map(SalesDailyData::getTotalProfit)
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                avgProfit.add(monthProfit.divide(new BigDecimal(monthCustomers), 2, RoundingMode.HALF_UP));
            } else {
                avgConsumption.add(BigDecimal.ZERO);
                avgProfit.add(BigDecimal.ZERO);
            }
        }

        trend.setMonths(months);
        trend.setAvgConsumption(avgConsumption);
        trend.setAvgProfit(avgProfit);
        result.setTrend(trend);

        return result;
    }

    @Override
    public ShopAnalysisVO getShopAnalysis(DashboardQueryDTO queryDTO) {
        ShopAnalysisVO result = new ShopAnalysisVO();

        // 1. 获取查询时间范围
        LocalDate endDate = queryDTO.getEndDate();
        LocalDate startDate = queryDTO.getStartDate();

        // 2. 构建查询条件
        String operator = queryDTO.getOperator();
        String amount = queryDTO.getAmount();

        // 3. 查询基础数据
        List<SalesDailyData> salesData = salesDailyDataMapper.selectByConditions(
                startDate, endDate,
                null,  // category
                queryDTO.getCity(),
                null,  // shopId
                null,  // gender
                null   // ageRange
        );

        if (!salesData.isEmpty()) {
            // 4. 按商店分组并筛选符合销售额条件的数据
            Map<String, List<SalesDailyData>> filteredShopGroups = salesData.stream()
                    .collect(Collectors.groupingBy(SalesDailyData::getShopId))
                    .entrySet().stream()
                    .filter(entry -> {
                        if (operator != null && amount != null && !amount.isEmpty()) {
                            try {
                                BigDecimal targetAmount = new BigDecimal(amount);
                                BigDecimal sales = entry.getValue().stream()
                                        .map(SalesDailyData::getTotalSales)
                                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                                return switch (operator) {
                                    case "=" -> sales.compareTo(targetAmount) == 0;
                                    case "<" -> sales.compareTo(targetAmount) < 0;
                                    case "<=" -> sales.compareTo(targetAmount) <= 0;
                                    case ">" -> sales.compareTo(targetAmount) > 0;
                                    case ">=" -> sales.compareTo(targetAmount) >= 0;
                                    default -> true;
                                };
                            } catch (NumberFormatException e) {
                                return true;
                            }
                        }
                        return true;
                    })
                    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

            // 5. 获取符合条件的商店的所有数据
            List<SalesDailyData> filteredData = filteredShopGroups.values().stream()
                    .flatMap(List::stream)
                    .collect(Collectors.toList());

            // 6. 使用筛选后的数据计算排名
            ShopAnalysisVO.ShopRankingVO rankingVO = calculateShopRanking(filteredData, operator, amount);
            result.setRankingData(rankingVO);

            // 7. 使用筛选后的数据计算城市数据
            ShopAnalysisVO.CityDataVO cityData = calculateCityData(filteredData);
            result.setCityData(cityData);

            // 8. 计算KPI和趋势数据（如果有商店和类别筛选）
            if (queryDTO.getShopId() != null || queryDTO.getCategory() != null) {
                List<SalesDailyData> kpiData = salesDailyDataMapper.selectByConditions(
                        startDate, endDate,
                        queryDTO.getCategory(),
                        queryDTO.getCity(),
                        queryDTO.getShopId(),
                        null,  // gender
                        null   // ageRange
                );

                if (!kpiData.isEmpty()) {
                    // 计算KPI数据
                    ShopAnalysisVO.ShopKpiVO kpiVO = calculateShopKpi(kpiData, startDate, endDate);
                    result.setKpiData(kpiVO);

                    // 计算趋势数据
                    ShopAnalysisVO.ShopTrendVO trendData = calculateShopTrend(kpiData);
                    result.setShopTrend(trendData);
                }
            }
        }

        return result;
    }

    // 计算商店KPI数据
    private ShopAnalysisVO.ShopKpiVO calculateShopKpi(
            List<SalesDailyData> salesData,
            LocalDate startDate,
            LocalDate endDate
    ) {
        ShopAnalysisVO.ShopKpiVO kpiData = new ShopAnalysisVO.ShopKpiVO();

        // 计算当前数据
        BigDecimal totalSales = salesData.stream()
                .map(SalesDailyData::getTotalSales)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        int totalVolume = salesData.stream()
                .mapToInt(SalesDailyData::getSalesVolume)
                .sum();

        kpiData.setTotalSales(totalSales);
        kpiData.setTotalVolume(totalVolume);

        // 如果有日期范围，计算同比环比
        if (startDate != null && endDate != null) {
            // 上周同期数据
            LocalDate lastWeekStart = startDate.minusWeeks(1);
            LocalDate lastWeekEnd = endDate.minusWeeks(1);
            List<SalesDailyData> lastWeekData = salesDailyDataMapper.selectByDateRange(lastWeekStart, lastWeekEnd);

            // 昨日数据
            LocalDate yesterday = endDate.minusDays(1);
            List<SalesDailyData> yesterdayData = salesDailyDataMapper.selectByDate(yesterday);

            // 计算上周数据
            BigDecimal lastWeekSales = lastWeekData.stream()
                    .map(SalesDailyData::getTotalSales)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            int lastWeekVolume = lastWeekData.stream()
                    .mapToInt(SalesDailyData::getSalesVolume)
                    .sum();

            // 计算昨日数据
            BigDecimal yesterdaySales = yesterdayData.stream()
                    .map(SalesDailyData::getTotalSales)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            int yesterdayVolume = yesterdayData.stream()
                    .mapToInt(SalesDailyData::getSalesVolume)
                    .sum();

            // 设置周同比和日环比
            kpiData.setSalesWeekOnWeek(calculateGrowthRate(totalSales, lastWeekSales));
            kpiData.setSalesDayOnDay(calculateGrowthRate(totalSales, yesterdaySales));
            kpiData.setVolumeWeekOnWeek(calculateGrowthRate(totalVolume, lastWeekVolume));
            kpiData.setVolumeDayOnDay(calculateGrowthRate(totalVolume, yesterdayVolume));
        } else {
            kpiData.setSalesWeekOnWeek(0.0);
            kpiData.setSalesDayOnDay(0.0);
            kpiData.setVolumeWeekOnWeek(0.0);
            kpiData.setVolumeDayOnDay(0.0);
        }

        return kpiData;
    }

    // 计算商店排名数据
    private ShopAnalysisVO.ShopRankingVO calculateShopRanking(
            List<SalesDailyData> salesData,
            String operator,
            String amount
    ) {
        // 按商店分组汇总数据
        Map<String, List<SalesDailyData>> shopGroups = salesData.stream()
                .collect(Collectors.groupingBy(SalesDailyData::getShopId));

        // 计算每个商店的销售额和利润
        List<AbstractMap.SimpleEntry<String, AbstractMap.SimpleEntry<BigDecimal, List<SalesDailyData>>>> shopStats =
                shopGroups.entrySet().stream()
                        .map(entry -> {
                            BigDecimal sales = entry.getValue().stream()
                                    .map(SalesDailyData::getTotalSales)
                                    .reduce(BigDecimal.ZERO, BigDecimal::add);
                            return new AbstractMap.SimpleEntry<>(
                                    entry.getKey(),
                                    new AbstractMap.SimpleEntry<>(sales, entry.getValue())
                            );
                        })
                        .filter(entry -> {
                            // 如果有销售额条件，进行过滤
                            if (operator != null && amount != null && !amount.isEmpty()) {
                                try {
                                    BigDecimal targetAmount = new BigDecimal(amount);
                                    BigDecimal sales = entry.getValue().getKey();
                                    return switch (operator) {
                                        case "=" -> sales.compareTo(targetAmount) == 0;
                                        case "<" -> sales.compareTo(targetAmount) < 0;
                                        case "<=" -> sales.compareTo(targetAmount) <= 0;
                                        case ">" -> sales.compareTo(targetAmount) > 0;
                                        case ">=" -> sales.compareTo(targetAmount) >= 0;
                                        default -> true;
                                    };
                                } catch (NumberFormatException e) {
                                    return true;
                                }
                            }
                            return true;
                        })
                        .sorted((a, b) -> b.getValue().getKey().compareTo(a.getValue().getKey()))  // 按销售额降序排序
                        .limit(15)  // 取前15名
                        .collect(Collectors.toList());

        // 准备返回数据
        ShopAnalysisVO.ShopRankingVO rankingData = new ShopAnalysisVO.ShopRankingVO();
        List<String> shops = new ArrayList<>();
        List<BigDecimal> sales = new ArrayList<>();
        List<BigDecimal> profits = new ArrayList<>();

        for (AbstractMap.SimpleEntry<String, AbstractMap.SimpleEntry<BigDecimal, List<SalesDailyData>>> entry : shopStats) {
            shops.add(entry.getKey());
            sales.add(entry.getValue().getKey());

            BigDecimal totalProfit = entry.getValue().getValue().stream()
                    .map(SalesDailyData::getTotalProfit)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            profits.add(totalProfit);
        }

        rankingData.setShops(shops);
        rankingData.setSales(sales);
        rankingData.setProfits(profits);

        return rankingData;
    }

    // 计算城市数据
    private ShopAnalysisVO.CityDataVO calculateCityData(List<SalesDailyData> salesData) {
        ShopAnalysisVO.CityDataVO cityData = new ShopAnalysisVO.CityDataVO();

        // 1. 计算城市商店分布
        Map<String, Set<String>> cityShops = salesData.stream()
                .collect(Collectors.groupingBy(
                        SalesDailyData::getCity,
                        Collectors.mapping(SalesDailyData::getShopId, Collectors.toSet())
                ));

        List<ShopAnalysisVO.CityShopVO> distribution = cityShops.entrySet().stream()
                .map(entry -> {
                    ShopAnalysisVO.CityShopVO cityShop = new ShopAnalysisVO.CityShopVO();
                    cityShop.setName(entry.getKey());
                    cityShop.setValue(entry.getValue().size());
                    return cityShop;
                })
                .sorted((a, b) -> b.getValue().compareTo(a.getValue()))
                .collect(Collectors.toList());

        // 2. 计算城市销售数据
        Map<String, List<SalesDailyData>> cityGroups = salesData.stream()
                .collect(Collectors.groupingBy(SalesDailyData::getCity));

        ShopAnalysisVO.CitySalesVO citySales = new ShopAnalysisVO.CitySalesVO();
        List<String> cities = new ArrayList<>();
        List<BigDecimal> sales = new ArrayList<>();
        List<Integer> volumes = new ArrayList<>();

        cityGroups.forEach((city, data) -> {
            cities.add(city);

            BigDecimal totalSales = data.stream()
                    .map(SalesDailyData::getTotalSales)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            sales.add(totalSales);

            int totalVolume = data.stream()
                    .mapToInt(SalesDailyData::getSalesVolume)
                    .sum();
            volumes.add(totalVolume);
        });

        citySales.setCities(cities);
        citySales.setSales(sales);
        citySales.setVolumes(volumes);

        cityData.setDistribution(distribution);
        cityData.setSales(citySales);

        return cityData;
    }

    // 计算商店趋势数据
    private ShopAnalysisVO.ShopTrendVO calculateShopTrend(List<SalesDailyData> salesData) {
        ShopAnalysisVO.ShopTrendVO trendData = new ShopAnalysisVO.ShopTrendVO();

        // 按月份分组
        Map<String, List<SalesDailyData>> monthlyData = salesData.stream()
                .collect(Collectors.groupingBy(data ->
                        data.getDate().getMonth().toString()));

        // 准备月份列表（按时间顺序）
        List<String> months = monthlyData.keySet().stream()
                .sorted()
                .collect(Collectors.toList());

        List<BigDecimal> sales = new ArrayList<>();
        List<BigDecimal> profits = new ArrayList<>();

        // 计算每月数据
        for (String month : months) {
            List<SalesDailyData> monthData = monthlyData.get(month);

            BigDecimal monthSales = monthData.stream()
                    .map(SalesDailyData::getTotalSales)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            sales.add(monthSales);

            BigDecimal monthProfit = monthData.stream()
                    .map(SalesDailyData::getTotalProfit)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            profits.add(monthProfit);
        }

        trendData.setMonths(months);
        trendData.setSales(sales);
        trendData.setProfits(profits);

        return trendData;
    }

    // 计算分布数据
    private List<CustomerAnalysisVO.DistributionItemVO> calculateDistribution(
            Map<String, List<SalesDailyData>> groups
    ) {
        int total = groups.values().stream()
                .mapToInt(list -> list.stream()
                        .mapToInt(SalesDailyData::getCustomerCount)
                        .sum())
                .sum();

        return groups.entrySet().stream()
                .map(entry -> {
                    CustomerAnalysisVO.DistributionItemVO item = new CustomerAnalysisVO.DistributionItemVO();
                    item.setName(entry.getKey());
                    int value = entry.getValue().stream()
                            .mapToInt(SalesDailyData::getCustomerCount)
                            .sum();
                    item.setValue(value);
                    item.setPercent(total > 0 ? (double) value / total * 100 : 0.0);
                    return item;
                })
                .sorted((a, b) -> b.getValue().compareTo(a.getValue()))
                .collect(Collectors.toList());
    }

    // 获取消费能力区间
    private String getConsumptionRange(BigDecimal avgConsumption) {
        double value = avgConsumption.doubleValue();
        if (value < 100)
            return "<100";
        if (value < 500)
            return "100-500";
        if (value < 1000)
            return "500-1000";
        if (value < 5000)
            return "1000-5000";
        return ">=5000";
    }

    @Override
    public DashboardVO getIncomeAnalysis(DashboardQueryDTO queryDTO) {
        DashboardVO result = new DashboardVO();
        // 获取最近6个月的数据
        // 设置默认日期范围
        LocalDate startDate = queryDTO.getStartDate() != null ? queryDTO.getStartDate() : LocalDate.of(2023, 1, 1);
        LocalDate endDate = queryDTO.getEndDate() != null ? queryDTO.getEndDate() : LocalDate.of(2023, 12, 31);

        log.warn("startDate: {}, endDate: {}", startDate, endDate);

        queryDTO.setStartDate(startDate);
        queryDTO.setEndDate(endDate);

        // 1. 获取基础数据
        List<SalesDailyData> salesData = salesDailyDataMapper.selectByConditions(
                startDate,
                endDate,
                queryDTO.getCategory(),
                queryDTO.getCity(),
                null,  // shopId
                null,  // gender
                null   // ageRange
        );

        if (!salesData.isEmpty()) {
            // 2. 计算KPI数据
            DashboardVO.KpiDataVO kpiData = calculateIncomeKpi(salesData, startDate, endDate);
            result.setKpiData(kpiData);

            // 3. 计算图表数据
            DashboardVO.ChartDataVO chartData = calculateIncomeChartData(salesData);
            result.setChartData(chartData);
        } else {
            // 如果没有数据，设置默认值
            DashboardVO.KpiDataVO kpiData = new DashboardVO.KpiDataVO();
            kpiData.setTotalSales(BigDecimal.ZERO);
            kpiData.setTotalProfit(BigDecimal.ZERO);
            kpiData.setMonthlyProfit(BigDecimal.ZERO);
            kpiData.setProfitWeekOnWeek(0.0);
            kpiData.setProfitDayOnDay(0.0);
            kpiData.setMonthlyProfitWeekOnWeek(0.0);
            kpiData.setMonthlyProfitDayOnDay(0.0);
            result.setKpiData(kpiData);

            DashboardVO.ChartDataVO chartData = new DashboardVO.ChartDataVO();
            chartData.setMonths(new ArrayList<>());
            chartData.setTotalSales(new ArrayList<>());
            chartData.setTotalProfits(new ArrayList<>());
            chartData.setMonthSales(new ArrayList<>());
            chartData.setMonthProfits(new ArrayList<>());
            chartData.setCategories(new ArrayList<>());
            chartData.setSalesVolumes(new ArrayList<>());
            chartData.setProducts(new ArrayList<>());
            chartData.setAvgProfits(new ArrayList<>());
            chartData.setProfitRates(new ArrayList<>());
            result.setChartData(chartData);
        }

        return result;
    }

    @Override
    @Transactional
    public Long createDashboard(DashboardCreateDTO createDTO) {
        // 验证数据
        if (createDTO.getCharts() != null) {
            for (DashboardChartDTO chartDTO : createDTO.getCharts()) {
                // 验证dataSource是有效的JSON字符串
                try {
                    // 如果已经是JSON字符串，不需要做任何处理
                    if (chartDTO.getDataSource() != null && !chartDTO.getDataSource().isEmpty()) {
                        // 尝试解析以验证它是有效的JSON
                        new ObjectMapper().readTree(chartDTO.getDataSource());
                    } else {
                        // 如果为空，设置为空JSON对象
                        chartDTO.setDataSource("{}");
                    }

                    // 同样处理options字段
                    if (chartDTO.getOptions() == null || chartDTO.getOptions().isEmpty()) {
                        chartDTO.setOptions("{}");
                    } else {
                        new ObjectMapper().readTree(chartDTO.getOptions());
                    }
                } catch (Exception e) {
                    throw new BusinessException("图表配置格式无效: " + e.getMessage());
                }
            }
        }

        // 创建仪表板信息
        DashboardInfo dashboardInfo = new DashboardInfo();
        BeanUtils.copyProperties(createDTO, dashboardInfo);
        dashboardInfo.setStatus("DRAFT"); // 默认为草稿状态
        dashboardInfo.setCreateTime(LocalDateTime.now());
        dashboardInfo.setUpdateTime(LocalDateTime.now());
        dashboardInfoMapper.insert(dashboardInfo);

        // 添加图表
        if (createDTO.getCharts() != null && !createDTO.getCharts().isEmpty()) {
            List<DashboardChart> charts = createDTO.getCharts().stream()
                    .map(chartDTO -> {
                        DashboardChart chart = new DashboardChart();
                        BeanUtils.copyProperties(chartDTO, chart);
                        chart.setDashboardId(dashboardInfo.getId());
                        chart.setCreateTime(LocalDateTime.now());
                        chart.setUpdateTime(LocalDateTime.now());
                        return chart;
                    })
                    .collect(Collectors.toList());

            for (DashboardChart chart : charts) {
                dashboardChartMapper.insert(chart);
            }
        }

        // 添加访问权限
        if (createDTO.getVisitorIds() != null && !createDTO.getVisitorIds().isEmpty()) {
            List<DashboardPermission> permissions = createDTO.getVisitorIds().stream()
                    .map(visitorId -> {
                        DashboardPermission permission = new DashboardPermission();
                        permission.setDashboardId(dashboardInfo.getId());
                        permission.setVisitorId(visitorId);
                        permission.setCreateTime(LocalDateTime.now());
                        permission.setUpdateTime(LocalDateTime.now());
                        return permission;
                    })
                    .collect(Collectors.toList());

            permissionMapper.batchInsert(permissions);
        }

        dashboardInfo.setType(String.valueOf(dashboardInfo.getId()));
        dashboardInfoMapper.updateById(dashboardInfo);
        return dashboardInfo.getId();
    }

    @Override
    public DashboardDetailVO getDashboardDetail(Long dashboardId) {
        DashboardInfo info = dashboardInfoMapper.selectById(dashboardId);
        if (info == null) {
            throw new BusinessException("仪表板不存在");
        }

        DashboardDetailVO vo = new DashboardDetailVO();
        BeanUtils.copyProperties(info, vo);

        // 获取图表信息
        List<DashboardChart> charts = dashboardChartMapper.selectByDashboardId(dashboardId);
        vo.setCharts(charts.stream()
                .map(chart -> {
                    DashboardChartVO chartVO = new DashboardChartVO();
                    BeanUtils.copyProperties(chart, chartVO);
                    return chartVO;
                })
                .collect(Collectors.toList()));

        // 获取访问者信息
        List<DashboardPermission> permissions = permissionMapper.selectByDashboardId(dashboardId);
        vo.setVisitors(permissions.stream()
                .map(permission -> {
                    DashboardDetailVO.VisitorVO visitorVO = new DashboardDetailVO.VisitorVO();
                    visitorVO.setVisitorId(permission.getVisitorId());

                    // TODO: 获取访问者名称
                    return visitorVO;
                })
                .collect(Collectors.toList()));

        return vo;
    }

    @Override
    public void updateDashboardStatus(Long dashboardId, String status) {
        if (!isValidStatus(status)) {
            throw new BusinessException("无效的状态值");
        }

        DashboardInfo info = dashboardInfoMapper.selectById(dashboardId);
        if (info == null) {
            throw new BusinessException("仪表板不存在");
        }

        // 如果要发布，检查是否有图表
        if ("PUBLISHED".equals(status)) {
            int chartCount = dashboardChartMapper.countByDashboardId(dashboardId);
            if (chartCount == 0) {
                throw new BusinessException("仪表板没有图表，无法发布");
            }
        }

        dashboardInfoMapper.updateStatus(dashboardId, status);
    }

    @Override
    public void addChart(Long dashboardId, DashboardChartDTO chartDTO) {
        DashboardInfo dashboard = dashboardInfoMapper.selectById(dashboardId);
        if (dashboard == null) {
            throw new BusinessException("仪表板不存在");
        }

        // 检查仪表板状态
        if ("PUBLISHED".equals(dashboard.getStatus())) {
            throw new BusinessException("已发布的仪表板不能添加图表");
        }

        DashboardChart chart = new DashboardChart();
        BeanUtils.copyProperties(chartDTO, chart);
        chart.setDashboardId(dashboardId);

        // 如果没有指定顺序，则放到最后
        if (chart.getDisplayOrder() == null) {
            Integer maxOrder = dashboardChartMapper.getMaxDisplayOrder(dashboardId);
            chart.setDisplayOrder(maxOrder == null ? 0 : maxOrder + 1);
        }

        dashboardChartMapper.insert(chart);
    }

    @Override
    public void deleteChart(Long chartId) {
        DashboardChart chart = dashboardChartMapper.selectById(chartId);
        if (chart == null) {
            throw new BusinessException("图表不存在");
        }

        // 检查仪表板状态
        DashboardInfo dashboard = dashboardInfoMapper.selectById(chart.getDashboardId());
        if (dashboard != null && "PUBLISHED".equals(dashboard.getStatus())) {
            throw new BusinessException("已发布的仪表板不能删除图表");
        }

        dashboardChartMapper.deleteById(chartId);
    }

    @Override
    public void updateChartOrder(Long chartId, Integer newOrder) {
        DashboardChart chart = dashboardChartMapper.selectById(chartId);
        if (chart == null) {
            throw new BusinessException("图表不存在");
        }

        // 检查仪表板状态
        DashboardInfo dashboard = dashboardInfoMapper.selectById(chart.getDashboardId());
        if (dashboard != null && "PUBLISHED".equals(dashboard.getStatus())) {
            throw new BusinessException("已发布的仪表板不能修改图表顺序");
        }

        chart.setDisplayOrder(newOrder);
        dashboardChartMapper.updateById(chart);
    }

    @Override
    public List<DashboardDetailVO> getUserDashboards(Long userId) {
        List<DashboardInfo> dashboards = dashboardInfoMapper.selectByOwnerId(userId);
        return dashboards.stream()
                .map(this::convertToDetailVO)
                .collect(Collectors.toList());
    }

    @Override
    public List<DashboardDetailVO> getPublishedDashboards() {
        List<DashboardInfo> dashboards = dashboardInfoMapper.selectByStatus("PUBLISHED");
        return dashboards.stream()
                .map(this::convertToDetailVO)
                .collect(Collectors.toList());
    }

    private DashboardDetailVO convertToDetailVO(DashboardInfo info) {
        DashboardDetailVO vo = new DashboardDetailVO();
        BeanUtils.copyProperties(info, vo);

        // 获取图表信息
        List<DashboardChart> charts = dashboardChartMapper.selectByDashboardId(info.getId());
        vo.setCharts(charts.stream()
                .map(chart -> {
                    DashboardChartVO chartVO = new DashboardChartVO();
                    BeanUtils.copyProperties(chart, chartVO);
                    return chartVO;
                })
                .collect(Collectors.toList()));

        return vo;
    }

    private boolean isValidStatus(String status) {
        return "DRAFT".equals(status) || "PUBLISHED".equals(status);
    }

    // 计算收入KPI数据
    private DashboardVO.KpiDataVO calculateIncomeKpi(
            List<SalesDailyData> salesData,
            LocalDate startDate,
            LocalDate endDate
    ) {
        DashboardVO.KpiDataVO kpiData = new DashboardVO.KpiDataVO();

        // 计算当前数据
        BigDecimal totalSales = salesData.stream()
                .map(SalesDailyData::getTotalSales)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        BigDecimal totalProfit = salesData.stream()
                .map(SalesDailyData::getTotalProfit)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        // 计算月度数据
        LocalDate monthStart = endDate.withDayOfMonth(1);
        BigDecimal monthlyProfit = salesData.stream()
                .filter(data -> !data.getDate().isBefore(monthStart))
                .map(SalesDailyData::getTotalProfit)
                .reduce(BigDecimal.ZERO, BigDecimal::add);

        kpiData.setTotalSales(totalSales);
        kpiData.setTotalProfit(totalProfit);
        kpiData.setMonthlyProfit(monthlyProfit);

        // 如果有日期范围，计算同比环比
        if (startDate != null && endDate != null) {
            // 上周同期数据
            LocalDate lastWeekStart = startDate.minusWeeks(1);
            LocalDate lastWeekEnd = endDate.minusWeeks(1);
            List<SalesDailyData> lastWeekData = salesDailyDataMapper.selectByDateRange(lastWeekStart, lastWeekEnd);

            // 昨日数据
            LocalDate yesterday = endDate.minusDays(1);
            List<SalesDailyData> yesterdayData = salesDailyDataMapper.selectByDate(yesterday);

            // 上月同期数据
            LocalDate lastMonthStart = monthStart.minusMonths(1);
            LocalDate lastMonthEnd = monthStart.minusDays(1);
            List<SalesDailyData> lastMonthData = salesDailyDataMapper.selectByDateRange(lastMonthStart, lastMonthEnd);

            // 计算上周数据
            BigDecimal lastWeekProfit = lastWeekData.stream()
                    .map(SalesDailyData::getTotalProfit)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            // 计算昨日数据
            BigDecimal yesterdayProfit = yesterdayData.stream()
                    .map(SalesDailyData::getTotalProfit)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            // 计算上月数据
            BigDecimal lastMonthProfit = lastMonthData.stream()
                    .map(SalesDailyData::getTotalProfit)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);

            // 设置周同比和日环比
            kpiData.setProfitWeekOnWeek(calculateGrowthRate(totalProfit, lastWeekProfit));
            kpiData.setProfitDayOnDay(calculateGrowthRate(totalProfit, yesterdayProfit));
            kpiData.setMonthlyProfitWeekOnWeek(calculateGrowthRate(monthlyProfit, lastWeekProfit));
            kpiData.setMonthlyProfitDayOnDay(calculateGrowthRate(monthlyProfit, yesterdayProfit));
        } else {
            kpiData.setProfitWeekOnWeek(0.0);
            kpiData.setProfitDayOnDay(0.0);
            kpiData.setMonthlyProfitWeekOnWeek(0.0);
            kpiData.setMonthlyProfitDayOnDay(0.0);
        }

        return kpiData;
    }

    // 计算收入图表数据
    private DashboardVO.ChartDataVO calculateIncomeChartData(List<SalesDailyData> salesData) {
        DashboardVO.ChartDataVO chartData = new DashboardVO.ChartDataVO();

        // 按月份分组
        Map<String, List<SalesDailyData>> monthlyData = salesData.stream()
                .collect(Collectors.groupingBy(data ->
                        data.getDate().getMonth().toString()));

        // 准备月份列表（按时间顺序）
        List<String> months = monthlyData.keySet().stream()
                .sorted()
                .collect(Collectors.toList());

        List<BigDecimal> totalSales = new ArrayList<>();
        List<BigDecimal> totalProfits = new ArrayList<>();
        List<BigDecimal> monthSales = new ArrayList<>();
        List<BigDecimal> monthProfits = new ArrayList<>();

        // 计算每月数据
        for (String month : months) {
            List<SalesDailyData> monthData = monthlyData.get(month);

            // 累计数据
            BigDecimal sales = monthData.stream()
                    .map(SalesDailyData::getTotalSales)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            totalSales.add(sales);

            BigDecimal profits = monthData.stream()
                    .map(SalesDailyData::getTotalProfit)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            totalProfits.add(profits);

            // 月度数据
            monthSales.add(sales);
            monthProfits.add(profits);
        }

        // 设置图表数据
        chartData.setMonths(months);
        chartData.setTotalSales(totalSales);
        chartData.setTotalProfits(totalProfits);
        chartData.setMonthSales(monthSales);
        chartData.setMonthProfits(monthProfits);

        // 计算产品类别销售量
        Map<String, Integer> categoryVolumes = salesData.stream()
                .collect(Collectors.groupingBy(
                        SalesDailyData::getCategory,
                        Collectors.summingInt(SalesDailyData::getSalesVolume)
                ));

        chartData.setCategories(new ArrayList<>(categoryVolumes.keySet()));
        chartData.setSalesVolumes(new ArrayList<>(categoryVolumes.values()));

        // 计算产品利润数据
        Map<String, List<SalesDailyData>> productGroups = salesData.stream()
                .collect(Collectors.groupingBy(SalesDailyData::getCategory));

        List<Map.Entry<String, BigDecimal>> profitStats = productGroups.entrySet().stream()
                .map(entry -> {
                    BigDecimal totalProfit = entry.getValue().stream()
                            .map(SalesDailyData::getTotalProfit)
                            .reduce(BigDecimal.ZERO, BigDecimal::add);
                    return new AbstractMap.SimpleEntry<>(entry.getKey(), totalProfit);
                })
                .sorted((a, b) -> b.getValue().compareTo(a.getValue()))
                .limit(5)
                .collect(Collectors.toList());

        List<String> products = profitStats.stream()
                .map(Map.Entry::getKey)
                .collect(Collectors.toList());
        List<BigDecimal> avgProfits = profitStats.stream()
                .map(Map.Entry::getValue)
                .collect(Collectors.toList());

        chartData.setProducts(products);
        chartData.setAvgProfits(avgProfits);

        // 计算利润率
        List<BigDecimal> profitRates = profitStats.stream()
                .map(entry -> {
                    List<SalesDailyData> productData = productGroups.get(entry.getKey());
                    BigDecimal totalSales2 = productData.stream()
                            .map(SalesDailyData::getTotalSales)
                            .reduce(BigDecimal.ZERO, BigDecimal::add);
                    return entry.getValue().divide(totalSales2, 4, RoundingMode.HALF_UP);
                })
                .collect(Collectors.toList());

        chartData.setProfitRates(profitRates);

        return chartData;
    }

    @Override
    public ChartOptionDTO getChartOptions() {
        ChartOptionDTO options = new ChartOptionDTO();

        // 获取所有图表类型
        List<ChartType> chartTypes = chartTypeMapper.selectList(null);
        List<ChartOptionDTO.ChartTypeOption> chartTypeOptions = chartTypes.stream()
                .map(ct -> {
                    ChartOptionDTO.ChartTypeOption option = new ChartOptionDTO.ChartTypeOption();
                    option.setValue(ct.getValue());
                    option.setLabel(ct.getLabel());
                    option.setIcon(ct.getIcon());
                    return option;
                })
                .collect(Collectors.toList());
        options.setChartTypes(chartTypeOptions);

        // 获取所有数据源
        List<DataSource> dataSources = dataSourceMapper.selectList(null);
        List<ChartOptionDTO.DataSourceOption> dataSourceOptions = dataSources.stream()
                .map(ds -> {
                    ChartOptionDTO.DataSourceOption option = new ChartOptionDTO.DataSourceOption();
                    option.setValue(ds.getValue());
                    option.setLabel(ds.getLabel());

                    // 获取该数据源支持的图表类型
                    List<String> supportedTypes = dataSourceMapper.selectSupportedChartTypesByDataSource(ds.getValue());
                    option.setSupportedChartTypes(supportedTypes);

                    return option;
                })
                .collect(Collectors.toList());
        options.setDataSources(dataSourceOptions);

        return options;
    }

    @Override
    public Map<String, Object> getChartData(String dataSource, String chartType, Map<String, Object> filters) {
        Map<String, Object> result = new HashMap<>();

        switch (dataSource) {
            case "totalSalesProfit":
                return getTotalSalesProfitData(chartType);
            case "orderCount":
                return getOrderCountData(chartType);
            case "salesVolume":
                return getSalesVolumeData(chartType);
            case "productCategorySales":
                return getProductCategorySalesData(chartType);
            case "productCategoryDistribution":
                return getProductCategoryDistributionData();
            case "customerCityDistribution":
                return getCustomerCityDistributionData();
            // 添加其他数据源的处理...
            default:
                throw new BusinessException("不支持的数据源类型: " + dataSource);
        }
    }

    // 实现各种数据获取方法
    private Map<String, Object> getTotalSalesProfitData(String chartType) {
        Map<String, Object> data = new HashMap<>();

        // 查询最近7天的总销售额和利润数据
        List<Map<String, Object>> recentData = dashboardInfoMapper.getRecentTotalSalesProfitData(7);

        List<String> dates = new ArrayList<>();
        List<BigDecimal> sales = new ArrayList<>();
        List<BigDecimal> profits = new ArrayList<>();

        for (Map<String, Object> item : recentData) {
            dates.add(item.get("date").toString());
            sales.add((BigDecimal) item.get("total_sales"));
            profits.add((BigDecimal) item.get("total_profit"));
        }

        data.put("xAxis", dates);
        data.put("series", Arrays.asList(
                new HashMap<String, Object>() {{
                    put("name", "销售额");
                    put("type", chartType);
                    put("data", sales);
                }},
                new HashMap<String, Object>() {{
                    put("name", "利润");
                    put("type", chartType);
                    put("data", profits);
                }}
        ));

        return data;
    }

    // 订单数量数据
    private Map<String, Object> getOrderCountData(String chartType) {
        Map<String, Object> data = new HashMap<>();

        // 查询最近7天的订单数量数据
        List<Map<String, Object>> orderData = salesDailyDataMapper.getRecentOrderCountData(7);

        List<String> dates = new ArrayList<>();
        List<Integer> counts = new ArrayList<>();

        for (Map<String, Object> item : orderData) {
            dates.add(item.get("date").toString());
            counts.add(((Number) item.get("order_count")).intValue());
        }

        data.put("xAxis", dates);
        data.put("series", Collections.singletonList(
                new HashMap<String, Object>() {{
                    put("name", "订单数量");
                    put("type", chartType);
                    put("data", counts);
                }}
        ));

        return data;
    }

    // 销售量数据
    private Map<String, Object> getSalesVolumeData(String chartType) {
        Map<String, Object> data = new HashMap<>();

        // 查询最近7天的销售量数据
        List<Map<String, Object>> volumeData = salesDailyDataMapper.getRecentSalesVolumeData(7);

        List<String> dates = new ArrayList<>();
        List<Integer> volumes = new ArrayList<>();

        for (Map<String, Object> item : volumeData) {
            dates.add(item.get("date").toString());
            volumes.add(((Number) item.get("sales_volume")).intValue());
        }

        data.put("xAxis", dates);
        data.put("series", Collections.singletonList(
                new HashMap<String, Object>() {{
                    put("name", "销售量");
                    put("type", chartType);
                    put("data", volumes);
                }}
        ));

        return data;
    }

    // 产品类别销售数据
    private Map<String, Object> getProductCategorySalesData(String chartType) {
        Map<String, Object> data = new HashMap<>();

        // 查询各产品类别的销售数据
        List<Map<String, Object>> categoryData = salesDailyDataMapper.getCategorySalesData();

        List<String> categories = new ArrayList<>();
        List<BigDecimal> sales = new ArrayList<>();

        for (Map<String, Object> item : categoryData) {
            categories.add(item.get("category").toString());
            sales.add((BigDecimal) item.get("total_sales"));
        }

        data.put("xAxis", categories);
        data.put("series", Collections.singletonList(
                new HashMap<String, Object>() {{
                    put("name", "类别销售额");
                    put("type", chartType);
                    put("data", sales);
                }}
        ));

        return data;
    }

    // 产品类别分布数据（饼图数据格式）
    private Map<String, Object> getProductCategoryDistributionData() {
        Map<String, Object> data = new HashMap<>();

        // 查询产品类别分布数据
        List<Map<String, Object>> distributionData = dashboardInfoMapper.getProductCategoryDistributionData();

        data.put("series", distributionData);

        return data;
    }

    // 客户城市分布数据（饼图数据格式）
    private Map<String, Object> getCustomerCityDistributionData() {
        Map<String, Object> data = new HashMap<>();

        // 查询客户城市分布数据
        List<Map<String, Object>> distributionData = dashboardInfoMapper.getCustomerCityDistributionData();

        data.put("series", distributionData);

        return data;
    }
}